package com.test.client.upload;

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.util.Observable;

import org.apache.log4j.Logger;

import com.test.client.filetransfer.FileDto;
import com.test.protocol.MemberDto;
import com.test.protocol.Protocol;

public class Upload extends Observable implements Runnable {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(Upload.class);
	public static final String UPSTATUSES[] = { "UPLOADING", "PAUSED",
		"COMPLETE", "CANCELLED", "ERROR" };

	
	public static final int UPLOADING = 0;
	public static final int PAUSED = 1;
	public static final int COMPLETE = 2;
	public static final int CANCELLED = 3;
	public static final int ERROR = 4;


	private FileInputStream fis;

	private BufferedOutputStream bos;
	long totalSize;
	int uploaded = 0;
	int status;

	private FileDto fileDto;
	private MemberDto memberDto;
	private Socket socket;


	public Upload(FileDto fileDto, MemberDto receiveMemberDto,Socket socket) {
		this.totalSize = fileDto.getFileSize();
		this.fileDto = fileDto;
		this.memberDto= receiveMemberDto;
		this.socket = socket;
		upload();
	}

	public void upload() {
		status = Upload.UPLOADING;
		Thread thread = new Thread(this);
		thread.start();
	}

	@Override
	public void run() {
		
		try {
			fis = new FileInputStream(fileDto.getFile());
			bos = new BufferedOutputStream(socket.getOutputStream());
			while (status == Upload.UPLOADING) {
				byte[] buffer = this.getBufferSize();
				int read = fis.read(buffer);
				if (read == -1 || uploaded >= totalSize) {
					break;
				}
				bos.write(buffer, 0, read);
				uploaded += read;

				stateChanged();
			}
			if(status == Upload.UPLOADING){
				status = Upload.COMPLETE;
				stateChanged();
			}
		} catch (FileNotFoundException e) {
			logger.error("run()", e); //$NON-NLS-1$

			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("run()", e); //$NON-NLS-1$

			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if (fis != null) {
					fis.close();
				}
				if (bos != null) {
					bos.close();
				}
			} catch (IOException e) {
				logger.error("run()", e); //$NON-NLS-1$

				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}


	}

	private void stateChanged() {
		setChanged();
		notifyObservers();
	}

	private byte[] getBufferSize() {
		byte[] buffer;
		if (totalSize - uploaded > Protocol.MAX_SIZE) {
			buffer = new byte[Protocol.MAX_SIZE];
		} else {
			buffer = new byte[(int) (totalSize - uploaded)];
		}
		return buffer;
	}

	public int getTotalSize() {
		return (int)totalSize;
	}

	public String getFileName() {
		String returnString = fileDto.getFile().getName();
		return returnString;
	}

	public int getStatus() {
		return status;
	}

	public String getReceiver() {
		String returnString = memberDto.getName();
		return returnString;
	}

	public float getProgress() {
		float returnfloat = ((float) uploaded / totalSize) * 100;
		return returnfloat;
	}

	public void pause() {
		status = Upload.PAUSED;
		stateChanged();
	}

	public void cancel() {
		status = Upload.CANCELLED;
		stateChanged();
	}

	public void error() {
		status = Upload.ERROR;
		stateChanged();
	}

	public void resume() {
		status = Upload.UPLOADING;
		stateChanged();
		upload();
	}

}
